// Copyright (C) 2010  Joan Puigcerver Perez, <joapuipe@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <SAXPeopleHandler.hpp>

#include <iostream>

SAXPeopleHandler::SAXPeopleHandler( Database * database,
				    std::ostream& logf, 
				    ost::Mutex& logm ) 
  : db(database), proc_aka(false), proc_actor(false), proc_director(false), 
    proc_producer(false), proc_writer(false), logfile(logf), log_mutex(logm)
{
}

void SAXPeopleHandler::startDocument ( )
{
  _kname = XMLString::transcode("name");
}

void SAXPeopleHandler::endDocument ( )
{
  XMLString::release(&_kname);
}

void SAXPeopleHandler::startElement ( const XMLCh* const uri,
				      const XMLCh* const localname,
				      const XMLCh* const qname,
				      const Attributes&  attrs )
{
  char * elem = XMLString::transcode(localname);

  if ( XMLString::equals(elem, "person") ) {
    const XMLCh * name = attrs.getValue( _kname );
    curr_person = createPerson( name );
  } else if ( XMLString::equals(elem, "aka") ) {
    proc_aka = true;
  } else if ( XMLString::equals(elem, "actor") ) {
    proc_actor = true;
  } else if ( XMLString::equals(elem, "director") ) {
    proc_director = true;
  } else if ( XMLString::equals(elem, "producer") ) {
    proc_producer = true;
  } else if ( XMLString::equals(elem, "writer" ) ) {
    proc_writer = true;
  }

  buffer.clear();
  
  XMLString::release(&elem);  
}

void SAXPeopleHandler::endElement( const XMLCh* const uri, 
				   const XMLCh* const localname,
				   const XMLCh* const qname )
{
  char * elem = XMLString::transcode(localname);

  if ( XMLString::equals(elem, "person") ) {
    curr_person = 0;
  } else if ( XMLString::equals(elem, "aka") ) {
    addAka( buffer );
    proc_aka = false;
  } else if ( XMLString::equals(elem, "movie" ) ) {
    if( proc_actor ) {
      addLink(buffer, Work::ID_ACTOR);
    } else if ( proc_director ) {
      addLink(buffer, Work::ID_DIRECTOR);
    } else if ( proc_producer ) {
      addLink(buffer, Work::ID_PRODUCER);
    } else if ( proc_writer ) {
      addLink(buffer, Work::ID_WRITER);
    }
  } else {
    proc_actor = false;
    proc_director = false;
    proc_producer = false;
    proc_writer = false;
  }

  XMLString::release(&elem);  
}


void SAXPeopleHandler::characters( const XMLCh* const chars,
				   const XMLSize_t length )
{
  if( proc_aka || proc_actor || proc_director | proc_producer || proc_writer ) 
    buffer.append(chars);
}

void SAXPeopleHandler::fatalError( const SAXParseException& exception )
{
  throw exception;
}

Person* SAXPeopleHandler::createPerson(const XMLCh * name)
{
  Person * pers;
  char * name_ch = XMLString::transcode( name );

  if ( !(pers = db->people.add_person(name_ch)) ) {
    print_log_line("DUPLICATED PERSON NAME! IGNORING INSERTION OF: " + std::string(name_ch), logfile, log_mutex);
  }

  XMLString::release(&name_ch);
  return pers;
}

void SAXPeopleHandler::error( const SAXParseException &exception )
{
  throw exception;
}

void SAXPeopleHandler::addAka(const XercesString& aka)
{
  if( curr_person == 0 ) {
    print_log_line("YOU SHOULD NOT BE HERE! - addAka()", logfile, log_mutex);
  } else {
    char * name_aka = XMLString::transcode( aka.c_str() );
    db->people.add_aka(name_aka, curr_person);
    XMLString::release(&name_aka);
  }
}

void SAXPeopleHandler::addLink(const XercesString& movie, Work work)
{
  if ( curr_person == 0) {
    print_log_line("YOU SHOULD NOT BE HERE! - addLink()", logfile, log_mutex);
  } else {
    char * movie_ch = XMLString::transcode( movie.c_str() );
    Movie * movie_ptr = db->movies.search( movie_ch );
    if (movie_ptr == NULL) {
      print_log_line("TITLE NOT FOUND: " + std::string(movie_ch) + " (IGNORING LINK)", logfile, log_mutex);
    } else  
      db->add_link(movie_ptr, curr_person, work);
    
    XMLString::release(&movie_ch);
  }
}

